<template>
  <div class="vue3-cron-plus-container">
    <el-tabs type="border-card">
      <!-- 秒 -->
      <el-tab-pane>
        <template #label>
          <span><el-icon>
              <Calendar />
            </el-icon> 秒</span>
        </template>
        <div class="tabBody myScroller">
          <el-row>
            <el-radio v-model="state.second.cronEvery" label="every">每秒</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.second.cronEvery" label="cycle">
              周期从
              <el-input-number v-model="state.second.cycleFrom" :min="0" :max="59" />
              到
              <el-input-number v-model="state.second.cycleTo" :min="0" :max="59" />
              秒
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.second.cronEvery" label="interval">
              周期从
              <el-input-number v-model="state.second.intervalFrom" :min="0" :max="59" />
              秒开始，每
              <el-input-number v-model="state.second.intervalStep" :min="1" :max="59" />
              秒执行一次
            </el-radio>
          </el-row>
          <el-row>
            <el-radio class="long" v-model="state.second.cronEvery" label="specific">
              指定
              <el-select multiple v-model="state.second.specificSpecific" style="width: 100%;">
                <el-option v-for="sec in 60" :key="sec - 1" :value="(sec - 1).toString().padStart(2, '0')">
                  {{ (sec - 1).toString().padStart(2, '0') }}
                </el-option>
              </el-select>
            </el-radio>
          </el-row>
        </div>
      </el-tab-pane>

      <!-- 分钟 -->
      <el-tab-pane>
        <template #label>
          <span><el-icon>
              <Calendar />
            </el-icon> 分钟</span>
        </template>
        <div class="tabBody myScroller">
          <el-row>
            <el-radio v-model="state.minute.cronEvery" label="every">每分钟</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.minute.cronEvery" label="cycle">
              周期从
              <el-input-number v-model="state.minute.cycleFrom" :min="0" :max="59" />
              到
              <el-input-number v-model="state.minute.cycleTo" :min="0" :max="59" />
              分钟
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.minute.cronEvery" label="interval">
              周期从
              <el-input-number v-model="state.minute.intervalFrom" :min="0" :max="59" />
              分钟开始，每
              <el-input-number v-model="state.minute.intervalStep" :min="1" :max="59" />
              分钟执行一次
            </el-radio>
          </el-row>
          <el-row>
            <el-radio class="long" v-model="state.minute.cronEvery" label="specific">
              指定
              <el-select multiple v-model="state.minute.specificSpecific" style="width: 100%;">
                <el-option v-for="min in 60" :key="min - 1" :value="(min - 1).toString().padStart(2, '0')">
                  {{ (min - 1).toString().padStart(2, '0') }}
                </el-option>
              </el-select>
            </el-radio>
          </el-row>
        </div>
      </el-tab-pane>

      <!-- 小时 -->
      <el-tab-pane>
        <template #label>
          <span><el-icon>
              <Calendar />
            </el-icon> 小时</span>
        </template>
        <div class="tabBody myScroller">
          <el-row>
            <el-radio v-model="state.hour.cronEvery" label="every">每小时</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.hour.cronEvery" label="cycle">
              周期从
              <el-input-number v-model="state.hour.cycleFrom" :min="0" :max="23" />
              到
              <el-input-number v-model="state.hour.cycleTo" :min="0" :max="23" />
              小时
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.hour.cronEvery" label="interval">
              周期从
              <el-input-number v-model="state.hour.intervalFrom" :min="0" :max="23" />
              小时开始，每
              <el-input-number v-model="state.hour.intervalStep" :min="1" :max="23" />
              小时执行一次
            </el-radio>
          </el-row>
          <el-row>
            <el-radio class="long" v-model="state.hour.cronEvery" label="specific">
              指定
              <el-select multiple v-model="state.hour.specificSpecific" style="width: 100%;">
                <el-option v-for="hour in 24" :key="hour - 1" :value="(hour - 1).toString().padStart(2, '0')">
                  {{ (hour - 1).toString().padStart(2, '0') }}
                </el-option>
              </el-select>
            </el-radio>
          </el-row>
        </div>
      </el-tab-pane>

      <!-- 日 -->
      <el-tab-pane>
        <template #label>
          <span><el-icon>
              <Calendar />
            </el-icon> 日</span>
        </template>
        <div class="tabBody myScroller">
          <el-row>
            <el-radio v-model="state.day.cronEvery" label="every">每日</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.day.cronEvery" label="unspecified">不指定</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.day.cronEvery" label="cycle">
              周期从
              <el-input-number v-model="state.day.cycleFrom" :min="1" :max="31" />
              到
              <el-input-number v-model="state.day.cycleTo" :min="1" :max="31" />
              日
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.day.cronEvery" label="interval">
              周期从
              <el-input-number v-model="state.day.intervalFrom" :min="1" :max="31" />
              日开始，每
              <el-input-number v-model="state.day.intervalStep" :min="1" :max="31" />
              日执行一次
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.day.cronEvery" label="workday">
              每月
              <el-input-number v-model="state.day.workday" :min="1" :max="31" />
              号最近的那个工作日
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.day.cronEvery" label="last">本月最后一天</el-radio>
          </el-row>
          <el-row>
            <el-radio class="long" v-model="state.day.cronEvery" label="specific">
              指定
              <el-select multiple v-model="state.day.specificSpecific" style="width: 100%;">
                <el-option v-for="day in 31" :key="day" :value="day.toString().padStart(2, '0')">
                  {{ day.toString().padStart(2, '0') }}
                </el-option>
              </el-select>
            </el-radio>
          </el-row>
        </div>
      </el-tab-pane>

      <!-- 月 -->
      <el-tab-pane>
        <template #label>
          <span><el-icon>
              <Calendar />
            </el-icon> 月</span>
        </template>
        <div class="tabBody myScroller">
          <el-row>
            <el-radio v-model="state.month.cronEvery" label="every">每月</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.month.cronEvery" label="cycle">
              周期从
              <el-input-number v-model="state.month.cycleFrom" :min="1" :max="12" />
              到
              <el-input-number v-model="state.month.cycleTo" :min="1" :max="12" />
              月
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.month.cronEvery" label="interval">
              周期从
              <el-input-number v-model="state.month.intervalFrom" :min="1" :max="12" />
              月开始，每
              <el-input-number v-model="state.month.intervalStep" :min="1" :max="12" />
              月执行一次
            </el-radio>
          </el-row>
          <el-row>
            <el-radio class="long" v-model="state.month.cronEvery" label="specific">
              指定
              <el-select multiple v-model="state.month.specificSpecific" style="width: 100%;">
                <el-option v-for="month in 12" :key="month" :value="month.toString().padStart(2, '0')">
                  {{ month.toString().padStart(2, '0') }}
                </el-option>
              </el-select>
            </el-radio>
          </el-row>
        </div>
      </el-tab-pane>

      <!-- 周 -->
      <el-tab-pane>
        <template #label>
          <span><el-icon>
              <Calendar />
            </el-icon> 周</span>
        </template>
        <div class="tabBody myScroller">
          <el-row>
            <el-radio v-model="state.week.cronEvery" label="unspecified">不指定</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.week.cronEvery" label="cycle">
              周期从星期
              <el-input-number v-model="state.week.cycleFrom" :min="1" :max="7" />
              到星期
              <el-input-number v-model="state.week.cycleTo" :min="1" :max="7" />
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.week.cronEvery" label="nth">
              第
              <el-input-number v-model="state.week.nthWeek" :min="1" :max="5" />
              周的星期
              <el-input-number v-model="state.week.nthDay" :min="1" :max="7" />
            </el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.week.cronEvery" label="last">
              本月最后一个星期
              <el-input-number v-model="state.week.lastDay" :min="1" :max="7" />
            </el-radio>
          </el-row>
          <el-row>
            <el-radio class="long" v-model="state.week.cronEvery" label="specific">
              指定
              <el-select multiple v-model="state.week.specificSpecific" style="width: 100%;">
                <el-option v-for="day in 7" :key="day" :value="day.toString()">
                  星期{{ ['日', '一', '二', '三', '四', '五', '六'][day - 1] }}
                </el-option>
              </el-select>
            </el-radio>
          </el-row>
        </div>
      </el-tab-pane>

      <!-- 年 -->
      <el-tab-pane>
        <template #label>
          <span><el-icon>
              <Calendar />
            </el-icon> 年</span>
        </template>
        <div class="tabBody myScroller">
          <el-row>
            <el-radio v-model="state.year.cronEvery" label="unspecified">不指定</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.year.cronEvery" label="yearly">每年</el-radio>
          </el-row>
          <el-row>
            <el-radio v-model="state.year.cronEvery" label="cycle">
              周期从
              <el-input-number v-model="state.year.cycleFrom" :min="1970" :max="2099" />
              到
              <el-input-number v-model="state.year.cycleTo" :min="1970" :max="2099" />
              年
            </el-radio>
          </el-row>
        </div>
      </el-tab-pane>
    </el-tabs>

    <!-- 表达式显示区域 -->
    <div class="expression-section">
      <div class="expression-header">
        <h3>&lt;/&gt; 表达式</h3>
      </div>

      <div class="expression-table">
        <el-table :data="[expressionData]" border>
          <el-table-column v-for="field in fields" :key="field.name" :prop="field.name" :label="field.label"
            align="center">
            <template #default="scope">
              <span class="field-value">{{ scope.row[field.name] }}</span>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <div class="cron-result">
        <div class="cron-expression-display">
          <strong>Cron表达式：</strong>
          <el-tag type="info" class="cron-string">{{ state.generatedCron }}</el-tag>
        </div>
        <div class="error-message" v-if="state.errorMessage">
          <el-alert :title="state.errorMessage" type="error" :closable="false" />
        </div>
        <div class="action-buttons">
          <el-button type="primary" @click="generateCron">生成表达式</el-button>
          <el-button @click="parseCron">反解析</el-button>
          <el-button type="success" @click="copyCron">复制</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { reactive, computed } from "vue";
import { Calendar } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';

const fields = [
  { name: 'second', label: '秒' },
  { name: 'minute', label: '分钟' },
  { name: 'hour', label: '小时' },
  { name: 'day', label: '日' },
  { name: 'month', label: '月' },
  { name: 'week', label: '周' },
  { name: 'year', label: '年' }
];

const state = reactive({
  // 秒配置
  second: {
    cronEvery: 'every',
    cycleFrom: 1,
    cycleTo: 2,
    intervalFrom: 0,
    intervalStep: 1,
    specificSpecific: ['00']
  },
  // 分钟配置
  minute: {
    cronEvery: 'every',
    cycleFrom: 1,
    cycleTo: 2,
    intervalFrom: 0,
    intervalStep: 1,
    specificSpecific: []
  },
  // 小时配置
  hour: {
    cronEvery: 'every',
    cycleFrom: 0,
    cycleTo: 2,
    intervalFrom: 0,
    intervalStep: 1,
    specificSpecific: []
  },
  // 日配置
  day: {
    cronEvery: 'every',
    cycleFrom: 1,
    cycleTo: 2,
    intervalFrom: 1,
    intervalStep: 1,
    workday: 1,
    specificSpecific: []
  },
  // 月配置
  month: {
    cronEvery: 'every',
    cycleFrom: 1,
    cycleTo: 2,
    intervalFrom: 1,
    intervalStep: 1,
    specificSpecific: []
  },
  // 周配置
  week: {
    cronEvery: 'unspecified',
    cycleFrom: 1,
    cycleTo: 2,
    nthWeek: 1,
    nthDay: 1,
    lastDay: 1,
    specificSpecific: []
  },
  // 年配置
  year: {
    cronEvery: 'unspecified',
    cycleFrom: 2018,
    cycleTo: 2019
  },
  generatedCron: '* * * * * ? *',
  errorMessage: ''
});


const isOnlyMinuteChanged = computed(() => {
  return state.minute.cronEvery !== 'every' &&
    state.second.cronEvery === 'every' &&
    state.hour.cronEvery === 'every' &&
    state.day.cronEvery === 'every' &&
    state.month.cronEvery === 'every' &&
    state.week.cronEvery === 'unspecified' &&
    state.year.cronEvery === 'unspecified';
});

const isOnlyHourChanged = computed(() => {
  return state.hour.cronEvery !== 'every' &&
    state.second.cronEvery === 'every' &&
    state.minute.cronEvery === 'every' &&
    state.day.cronEvery === 'every' &&
    state.month.cronEvery === 'every' &&
    state.week.cronEvery === 'unspecified' &&
    state.year.cronEvery === 'unspecified';
});

const isOnlyDayChanged = computed(() => {
  return state.day.cronEvery !== 'every' &&
    state.second.cronEvery === 'every' &&
    state.minute.cronEvery === 'every' &&
    state.hour.cronEvery === 'every' &&
    state.month.cronEvery === 'every' &&
    state.week.cronEvery === 'unspecified' &&
    state.year.cronEvery === 'unspecified';
});

const isOnlyMonthChanged = computed(() => {
  return state.month.cronEvery !== 'every' &&
    state.second.cronEvery === 'every' &&
    state.minute.cronEvery === 'every' &&
    state.hour.cronEvery === 'every' &&
    state.day.cronEvery === 'every' &&
    state.week.cronEvery === 'unspecified' &&
    state.year.cronEvery === 'unspecified';
});

const isOnlyYearChanged = computed(() => {
  return state.year.cronEvery !== 'unspecified' &&
    state.second.cronEvery === 'every' &&
    state.minute.cronEvery === 'every' &&
    state.hour.cronEvery === 'every' &&
    state.day.cronEvery === 'every' &&
    state.month.cronEvery === 'every' &&
    state.week.cronEvery === 'unspecified';
});
// 计算表达式表格数据
const expressionData = computed(() => {
  const data: any = {};
  fields.forEach(field => {
    data[field.name] = getFieldValue(field.name);
  });
  return data;
});

const getFieldValue = (field: string) => {
  const config = (state as any)[field];
  const formatNumber = (numStr: string) => {
    const num = parseInt(numStr, 10);
    return isNaN(num) ? numStr : num.toString();
  };

  switch (config.cronEvery) {
    case 'every':
      // 根据只改变某个字段的情况来替换 * 为 0
      if (field === 'second') {
        // 如果只改变分、时、天、月、年，秒要变成0
        if (isOnlyMinuteChanged.value || isOnlyHourChanged.value ||
          isOnlyDayChanged.value || isOnlyMonthChanged.value || isOnlyYearChanged.value) {
          return '0';
        }
      } else if (field === 'minute') {
        // 如果只改变时、天、月、年，分要变成0
        if (isOnlyHourChanged.value || isOnlyDayChanged.value ||
          isOnlyMonthChanged.value || isOnlyYearChanged.value) {
          return '0';
        }
      } else if (field === 'hour') {
        // 如果只改变天、月、年，时要变成0
        if (isOnlyDayChanged.value || isOnlyMonthChanged.value || isOnlyYearChanged.value) {
          return '0';
        }
      } else if (field === 'day') {
        // 如果只改变月、年，天要变成0
        if (isOnlyMonthChanged.value || isOnlyYearChanged.value) {
          return '0';
        }
      } else if (field === 'month') {
        // 如果只改变年，月要变成0
        if (isOnlyYearChanged.value) {
          return '0';
        }
      }
      return '*';

    case 'cycle':
      return `${formatNumber(config.cycleFrom.toString())}-${formatNumber(config.cycleTo.toString())}`;
    case 'interval':
      return `${formatNumber(config.intervalFrom.toString())}/${formatNumber(config.intervalStep.toString())}`;
    case 'specific':
      if (config.specificSpecific.length === 0) return '*';
      const formatted = config.specificSpecific.map((v: string) => formatNumber(v));
      return formatted.join(',');
    case 'workday':
      return `${formatNumber(config.workday.toString())}W`;
    case 'last':
      return 'L';
    case 'nth':
      return `${formatNumber(config.nthDay.toString())}#${formatNumber(config.nthWeek.toString())}`;
    case 'yearly':
      return '';
    case 'unspecified':
      if (field === 'week') return '?';
      if (field === 'year') return '';
      return '*';
    default:
      return '*';
  }
};

const generateCron = () => {
  try {
    let cronParts = fields.map(field => {
      const value = getFieldValue(field.name);
      return value;
    }).filter(value => value !== '');

    // 处理每年逻辑（覆盖前面的规则）
    if (state.week.cronEvery === 'yearly') {
      cronParts = ['0', '0', '0', '1', '1', '?', '*'];
    }

    state.generatedCron = cronParts.join(' ');
    state.errorMessage = '';

    // 验证日和周的冲突（每年选项不需要验证）
    if (state.week.cronEvery !== 'yearly') {
      const dayIndex = fields.findIndex(f => f.name === 'day');
      const weekIndex = fields.findIndex(f => f.name === 'week');
      const dayValue = cronParts[dayIndex];
      const weekValue = cronParts[weekIndex];

      if (dayValue !== '?' && weekValue !== '?') {
        state.errorMessage = '日和周不能同时指定具体值，其中一个必须为?';
      }
    }
  } catch (error) {
    state.errorMessage = '生成表达式时出现错误';
  }
};
const parseCron = () => {
  ElMessage.info('反解析功能待实现');
};

const copyCron = () => {
  navigator.clipboard.writeText(state.generatedCron).then(() => {
    ElMessage.success('Cron表达式已复制到剪贴板');
  });
};

// 初始化生成表达式
generateCron();
</script>

<style lang="scss" scoped>
.vue3-cron-plus-container {
  max-width: 1200px;
  margin: 0 auto;

  .el-row {
    margin-bottom: 10px;
  }

  .tabBody {
    padding: 10px;
  }

  .long {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .myScroller {
    max-height: 400px;
    overflow-y: auto;
  }

  .expression-section {
    margin-top: 20px;
    padding: 20px;
    border: 1px solid #e4e7ed;
    border-radius: 4px;
  }

  .expression-header {
    margin-bottom: 15px;

    h3 {
      margin: 0;
      color: #303133;
    }
  }

  .expression-table {
    margin-bottom: 20px;
  }

  .field-value {
    font-family: 'Courier New', monospace;
    font-weight: bold;
  }

  .cron-result {
    background: #f8f9fa;
    padding: 15px;
    border-radius: 5px;
  }

  .cron-expression-display {
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
  }

  .cron-string {
    font-family: 'Courier New', monospace;
    font-size: 14px;
    padding: 4px 8px;
  }

  .error-message {
    margin-bottom: 10px;
  }

  .action-buttons {
    display: flex;
    gap: 10px;
  }
}
</style>